package service

import (
	"fmt"
	"os"
	"path/filepath"
	"regexp"
	"strings"
	"sync"
	"unicode"
)

type ClassifyRequest struct {
	Years     []string `json:"years"`
	Provinces []string `json:"provinces"`
	Cities    []string `json:"cities"`
	Grades    []string `json:"grades"`
	Subjects  []string `json:"subjects"`
	SourceDir string   `json:"sourceDir"`
	TargetDir string   `json:"targetDir"`
}

type ClassifyService struct {
	progressChan chan int
	messageChan  chan string
}

func NewClassifyService(progressChan chan int, messageChan chan string) *ClassifyService {
	return &ClassifyService{
		progressChan: progressChan,
		messageChan:  messageChan,
	}
}

func (s *ClassifyService) Classify(req *ClassifyRequest) error {
	// 验证目录是否存在
	if _, err := os.Stat(req.SourceDir); os.IsNotExist(err) {
		return fmt.Errorf("源目录不存在: %s", req.SourceDir)
	}

	// 遍历源目录
	files, err := s.scanFiles(req.SourceDir)
	if err != nil {
		return fmt.Errorf("扫描源目录失败: %v", err)
	}

	// 开始分类文件
	totalFiles := len(files)
	s.messageChan <- fmt.Sprintf("共发现 %d 个文件待分类", totalFiles)

	processed := 0
	var wg sync.WaitGroup
	for i, file := range files {
		wg.Add(1)
		go func(i int, file string) {
			defer wg.Done()
			if err := s.classifyFile(file, req); err != nil {
				s.messageChan <- fmt.Sprintf("处理文件失败 %s: %v", file, err)
			}
			processed++
			s.progressChan <- processed * 100 / totalFiles
			s.messageChan <- fmt.Sprintf("进度：%d/%d", processed, totalFiles)
		}(i, file)
	}

	wg.Wait()
	s.progressChan <- 100
	s.messageChan <- fmt.Sprintf("进度：%d/%d", totalFiles, totalFiles)
	s.messageChan <- "文件分类完成"
	return nil
}

func (s *ClassifyService) scanFiles(sourceDir string) ([]string, error) {
	var files []string
	err := filepath.Walk(sourceDir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if strings.HasPrefix(info.Name(), ".") {
			if info.IsDir() {
				return filepath.SkipDir // 跳过隐藏目录
			}
			return nil // 跳过隐藏文件
		}
		if !info.IsDir() {
			files = append(files, path)
		}
		return nil
	})
	return files, err
}

func (s *ClassifyService) classifyFile(filePath string, req *ClassifyRequest) error {
	fileName := filepath.Base(filePath)
	
	// 创建新的请求副本，避免并发修改
	reqCopy := *req
	
	// 检查文件名是否符合分类条件
	if !s.matchFileConditions(fileName, &reqCopy) {
		s.messageChan <- fmt.Sprintf("跳不符合条件的文件: %s", fileName)
		return nil
	}

	// 创建目标目录结构
	year := reqCopy.Years[0]
	// 检查文件名中是否包含完整年份
	yearPattern := regexp.MustCompile(`\d{4}`)
	if matches := yearPattern.FindString(filepath.Base(filePath)); matches != "" {
		year = matches
	} else if len(year) == 3 && (strings.HasSuffix(year, "春") || strings.HasSuffix(year, "秋")) {
		// 如果是季节格式（如24春），转换为完整年份
		year = "20" + year[:2]
	}
	
	targetPath := filepath.Join(
		reqCopy.TargetDir,
		year,
		reqCopy.Provinces[0],
		reqCopy.Cities[0],
		reqCopy.Grades[0],
		reqCopy.Subjects[0],
	)
	if err := os.MkdirAll(targetPath, 0755); err != nil {
		return fmt.Errorf("创建目标目录失败: %v", err)
	}

	// 构建目标文件路径
	targetFilePath := filepath.Join(targetPath, fileName)

	// 移动文件
	if err := os.Rename(filePath, targetFilePath); err != nil {
		return fmt.Errorf("移动文件失败: %v", err)
	}

	s.messageChan <- fmt.Sprintf("成功移动文件: %s", fileName)
	return nil
}

// 获取省份的所有可能形式
func getProvinceVariants(province string) []string {
	// 移除"省"、"自治区"、"特别行政区"等后缀
	variants := []string{province}
	suffixes := []string{"省", "自治区", "特别行政区"}
	for _, suffix := range suffixes {
		if strings.HasSuffix(province, suffix) {
			variants = append(variants, strings.TrimSuffix(province, suffix))
		}
	}
	return variants
}

// 获取城市的所有可能形式
func getCityVariants(city string) []string {
	// 移除"市"后缀
	variants := []string{city}
	if strings.HasSuffix(city, "市") {
		variants = append(variants, strings.TrimSuffix(city, "市"))
	}
	// 如果是"武汉市"这样的城市，添加更多变体
	if base := strings.TrimSuffix(city, "市"); base != city {
		variants = append(variants, base+"", base+"市")
	}
	return variants
}

// 获取年级的所有可能形式
func getGradeVariants(grade string) []string {
	gradeMap := map[string]string{
		"一年级": "1年级",
		"二年级": "2年级",
		"三年级": "3年级",
		"四年级": "4年级",
		"五年级": "5年级",
		"六年级": "6年级",
	}
	
	// 反向映射，支持数字形式匹配到汉字形式
	reverseMap := map[string]string{
		"1年级": "一年级",
		"2年级": "二年级",
		"3年级": "三年级",
		"4年级": "四年级",
		"5年级": "五年级",
		"6年级": "六年级",
	}
	
	variants := []string{grade}
	if mapped, ok := gradeMap[grade]; ok {
		variants = append(variants, mapped)
	}
	if mapped, ok := reverseMap[grade]; ok {
		variants = append(variants, mapped)
	}
	return variants
}

// 获取学科的所有可形式
func getSubjectVariants(subject string) []string {
	// 添加更多的匹配形式
	subjectAliases := map[string][]string{
		"语文": []string{"语", "语文", "yuwen", "yw"},
		"数学": []string{"数", "数学", "shuxue", "sx", "s"},
		"英语": []string{"英", "英语", "yingyu", "yy", "y"},
	}
	
	variants := []string{subject}
	if aliases, ok := subjectAliases[subject]; ok {
		variants = append(variants, aliases...)
	}
	return variants
}

// 获取年份的所有可能形式
func getYearVariants(year string) []string {
	variants := []string{year}
	// 如果是类似"24春"的格式，添加"2024"的匹配
	if len(year) == 3 && (strings.HasSuffix(year, "春") || strings.HasSuffix(year, "秋")) {
		yearPrefix := year[:2]
		fullYear := "20" + yearPrefix
		variants = append(variants, fullYear)
	}
	// 如果是类似"2023-2024"的格式，提取最后一个年份
	if strings.Contains(year, "-") {
		parts := strings.Split(year, "-")
		if len(parts) > 0 {
			lastYear := parts[len(parts)-1]
			if len(lastYear) == 4 {
				variants = append(variants, lastYear)
			}
		}
	}
	return variants
}

func (s *ClassifyService) matchFileConditions(fileName string, req *ClassifyRequest) bool {
	// 将文件名转换为小写并移除所有空格
	fileName = strings.ToLower(fileName)
	fileName = strings.ReplaceAll(fileName, " ", "")
	fileName = strings.ReplaceAll(fileName, "_", "")
	fileName = strings.ReplaceAll(fileName, "-", "")
	fileName = strings.ReplaceAll(fileName, ".", "")
	fileName = strings.ReplaceAll(fileName, "（", "(")
	fileName = strings.ReplaceAll(fileName, "）", ")")
	fileName = strings.ReplaceAll(fileName, "【", "[")
	fileName = strings.ReplaceAll(fileName, "】", "]")
	
	// 存储匹配到的值，用于创建目标目录
	var matchedValues struct {
		year     string
		province string
		city     string
		grade    string
		subject  string
	}
	
	// 1. 匹配年份
	yearMatch := false
	yearPattern := regexp.MustCompile(`\d{4}`)
	if years := yearPattern.FindAllString(fileName, -1); len(years) > 0 {
		lastYear := years[len(years)-1]
		for _, year := range req.Years {
			if strings.HasPrefix(year, lastYear[2:]) {
				yearMatch = true
				matchedValues.year = year
				break
			}
		}
	} else {
		shortYearPattern := regexp.MustCompile(`\d{2}[春秋]`)
		if years := shortYearPattern.FindAllString(fileName, -1); len(years) > 0 {
			shortYear := years[0]
			for _, year := range req.Years {
				if year == shortYear {
					yearMatch = true
					matchedValues.year = year
					break
				}
			}
		}
	}
	if !yearMatch {
		return false
	}
	
	// 2. 匹配省份
	provinceMatch := false
	for _, province := range req.Provinces {
		if strings.Contains(fileName, strings.ToLower(strings.TrimSuffix(province, "省"))) {
			provinceMatch = true
			matchedValues.province = province
			break
		}
	}
	if !provinceMatch {
		return false
	}
	
	// 3. 匹配城市
	cityMatch := false
	cityPositions := make(map[int]string)
	for _, city := range req.Cities {
		cityName := strings.ToLower(strings.TrimSuffix(city, "市"))
		pos := 0
		for {
			index := strings.Index(fileName[pos:], cityName)
			if index == -1 {
				break
			}
			actualPos := pos + index
			beforeOK := actualPos == 0 || !isChineseChar(rune(fileName[actualPos-1]))
			afterOK := actualPos+len(cityName) == len(fileName) || !isChineseChar(rune(fileName[actualPos+len(cityName)]))
			if beforeOK && afterOK {
				cityPositions[actualPos] = city
			}
			pos = actualPos + len(cityName)
		}
	}
	if len(cityPositions) > 0 {
		var firstPos int = -1
		for pos := range cityPositions {
			if firstPos == -1 || pos < firstPos {
				firstPos = pos
			}
		}
		cityMatch = true
		matchedValues.city = cityPositions[firstPos]
	}
	if !cityMatch {
		return false
	}
	
	// 4. 匹配年级
	gradeMatch := false
	for _, grade := range req.Grades {
		variants := getGradeVariants(grade)
		for _, variant := range variants {
			if strings.Contains(fileName, strings.ToLower(variant)) {
				gradeMatch = true
				matchedValues.grade = grade
				break
			}
		}
		if gradeMatch {
			break
		}
	}
	if !gradeMatch {
		return false
	}
	
	// 5. 匹配学科
	subjectMatch := false
	for _, subject := range req.Subjects {
		if strings.Contains(fileName, strings.ToLower(subject)) || 
			strings.Contains(fileName, "s") && subject == "数学" ||
			strings.Contains(fileName, "sx") && subject == "数学" {
			subjectMatch = true
			matchedValues.subject = subject
			break
		}
	}
	if !subjectMatch {
		return false
	}
	
	// 更新请求中的值为实际匹配到的值
	req.Years[0] = matchedValues.year
	req.Provinces[0] = matchedValues.province
	req.Cities[0] = matchedValues.city
	req.Grades[0] = matchedValues.grade
	req.Subjects[0] = matchedValues.subject
	
	return true
}

// 判断字符是否是汉字
func isChineseChar(r rune) bool {
	return unicode.Is(unicode.Han, r)
} 